package com.jspgou.cms.action.admin.main;

import static com.jspgou.cms.entity.Payment.OFFLINE;
import static com.jspgou.cms.entity.Payment.PAYMENT_TYPE;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import com.jspgou.core.entity.Website;
import com.jspgou.core.manager.LogMng;
import com.jspgou.core.web.SiteUtils;
import com.jspgou.core.web.WebErrors;
import com.jspgou.cms.entity.Payment;
import com.jspgou.cms.manager.PaymentMng;

@Controller
public class PaymentAct {
	private static final Logger log = LoggerFactory.getLogger(PaymentAct.class);

	@RequestMapping("/payment/v_list.do")
	public String list(Integer pageNo, HttpServletRequest request,
			ModelMap model) {
		List<Payment> list = manager.getList(SiteUtils.getWebId(request), true);
		Set<String> codeSet = new HashSet<String>();
		for (Payment p : list) {
			codeSet.add(p.getCode());
		}
		model.addAttribute("list", list);
		model.addAttribute("codeSet", codeSet);
		return "payment/list";
	}
	
	
	@RequestMapping("/payment/o_priority.do")
	public String priority(Long[] wids, Integer[] priority, Integer pageNo,
			HttpServletRequest request, ModelMap model) {
		WebErrors errors = validatePriority(wids, priority, request);
		if (errors.hasErrors()) {
			return errors.showErrorPage(model);
		}
		manager.updatePriority(wids, priority);
		model.addAttribute("message", "global.success");
		return list(pageNo, request, model);
	}

	@RequestMapping("/payment/v_add.do")
	public String add(String code, HttpServletRequest request, ModelMap model) {
		WebErrors errors = validateAdd(code, request);
		if (errors.hasErrors()) {
			return errors.showErrorPage(model);
		}
		return "payment/add_" + code;
	}

	@RequestMapping("/payment/v_edit.do")
	public String edit(Long id, String code, HttpServletRequest request,
			ModelMap model) {
		WebErrors errors = validateEdit(id, code, request);
		if (errors.hasErrors()) {
			return errors.showErrorPage(model);
		}
		Payment payment = manager.findById(id);
		model.addAttribute("payment", payment);
		model.addAttribute("cfg", payment.getCfg());
		return "payment/edit_" + code;
	}

	@RequestMapping("/payment/o_save.do")
	public String save(Payment bean, HttpServletRequest request, ModelMap model) {
		WebErrors errors = validateSave(bean, request);
		if (errors.hasErrors()) {
			return errors.showErrorPage(model);
		}
		if(bean.getIsDefault()){
			List<Payment> list=manager.getList((long)1, true);
			for(int i=0;i<list.size();i++){
				list.get(i).setIsDefault(false);
				manager.update(list.get(i), null);
			}
		}
		bean = manager.save(bean, getCfg(request));
		log.info("save Payment, id={}", bean.getId());
		logMng.operating(request, "添加支付方式", "id="+bean.getId()+" ;name="+bean.getName());
		return "redirect:v_list.do";
	}

	@RequestMapping("/payment/o_update.do")
	public String update(Payment bean, Integer pageNo,
			HttpServletRequest request, ModelMap model) {
		WebErrors errors = validateUpdate(bean.getId(), bean.getCode(), request);
		if (errors.hasErrors()) {
			return errors.showErrorPage(model);
		}
		if(bean.getIsDefault()){
			List<Payment> list=manager.getList((long)1, true);
			for(int i=0;i<list.size();i++){
				list.get(i).setIsDefault(false);
				manager.update(list.get(i), null);
			}
		}
		bean = manager.update(bean, getCfg(request));
		log.info("update Payment, id={}.", bean.getId());
		logMng.operating(request, "修改支付方式", "id="+bean.getId()+" ;name="+bean.getName());
		return list(pageNo, request, model);
	}

	@RequestMapping("/payment/o_delete.do")
	public String delete(Long[] ids, Integer pageNo,
			HttpServletRequest request, ModelMap model) {
		WebErrors errors = validateDelete(ids, request);
		if (errors.hasErrors()) {
			return errors.showErrorPage(model);
		}
		Payment[] beans = manager.deleteByIds(ids);
		for (Payment bean : beans) {
			log.info("delete Payment, id={}", bean.getId());
			logMng.operating(request, "删除支付方式", "id="+bean.getId()+" ;name="+bean.getName());
		}
		return list(pageNo, request, model);
	}

	private WebErrors validateAdd(String code, HttpServletRequest request) {
		WebErrors errors = WebErrors.create(request);
		Website web = SiteUtils.getWeb(request);
		if (vldCode(code, errors)) {
			return errors;
		}
		if (!code.equals(OFFLINE)
				&& manager.getByCode(code, web.getId()).size() > 0) {
			errors.addErrorCode("payment.paymemtExist", code);
			return errors;
		}
		return errors;
	}

	private WebErrors validateSave(Payment bean, HttpServletRequest request) {
		WebErrors errors = WebErrors.create(request);
		Website web = SiteUtils.getWeb(request);
		String code = bean.getCode();
		if (vldCode(code, errors)) {
			return errors;
		}
		if (!code.equals(OFFLINE)
				&& manager.getByCode(code, web.getId()).size() > 0) {
			errors.addErrorCode("payment.paymemtExist", code);
			return errors;
		}
		bean.setWebsite(web);
		return errors;
	}

	private WebErrors validateEdit(Long id, String code,
			HttpServletRequest request) {
		WebErrors errors = WebErrors.create(request);
		Website web = SiteUtils.getWeb(request);
		if (vldCode(code, errors)) {
			return errors;
		}
		if (vldExist(id, code, web.getId(), errors)) {
			return errors;
		}
		return errors;
	}

	private WebErrors validateUpdate(Long id, String code,
			HttpServletRequest request) {
		WebErrors errors = WebErrors.create(request);
		Website web = SiteUtils.getWeb(request);
		if (vldCode(code, errors)) {
			return errors;
		}
		if (vldExist(id, code, web.getId(), errors)) {
			return errors;
		}
		return errors;
	}

	private WebErrors validateDelete(Long[] ids, HttpServletRequest request) {
		WebErrors errors = WebErrors.create(request);
		Website web = SiteUtils.getWeb(request);
		errors.ifEmpty(ids, "ids");
		for (Long id : ids) {
			vldExist(id, null, web.getId(), errors);
		}
		return errors;
	}

	private boolean vldExist(Long id, String code, Long webId, WebErrors errors) {
		if (errors.ifNull(id, "id")) {
			return true;
		}
		Payment entity = manager.findById(id);
		if (errors.ifNotExist(entity, Payment.class, id)) {
			return true;
		}
		if (!entity.getWebsite().getId().equals(webId)) {
			errors.notInWeb(Payment.class, id);
			return true;
		}
		if (code != null && !entity.getCode().equals(code)) {
			errors.addErrorString("code invalid, entity code is '"
					+ entity.getCode() + "' and action code is '" + code + ";");
		}
		return false;
	}

	private boolean vldCode(String code, WebErrors errors) {
		if (errors.ifBlank(code, "code", 30)) {
			return true;
		}
		for (String s : PAYMENT_TYPE) {
			if (s.equals(code)) {
				return false;
			}
		}
		errors.addErrorString("not support code: " + code);
		return true;
	}

	private Map<String, String> getCfg(HttpServletRequest request) {
		Map<String, String> map = new HashMap<String, String>();
		Enumeration e = request.getParameterNames();
		String param = "cfg_";
		String name;
		while (e.hasMoreElements()) {
			name = (String) e.nextElement();
			if (name.startsWith(param)) {
				map.put(name.substring(param.length()), request
						.getParameter(name));
			}
		}
		return map;
	}

	private WebErrors validatePriority(Long[] wids, Integer[] priority,
			HttpServletRequest request) {
		WebErrors errors = WebErrors.create(request);
		if (errors.ifEmpty(wids, "wids")) {
			return errors;
		}
		if (errors.ifEmpty(priority, "priority")) {
			return errors;
		}
		if (wids.length != priority.length) {
			errors.addErrorString("wids length not equals priority length");
			return errors;
		}
		for (int i = 0, len = wids.length; i < len; i++) {
			vldExist(wids[i], errors);
			if (priority[i] == null) {
				priority[i] = 0;
			}
		}
		return errors;
	}
	
	private boolean vldExist(Long id, WebErrors errors) {
		Payment payment = manager.findById(id);
		return errors.ifNotExist(payment, Payment.class, id);
	}
	
	
	@Autowired
	private PaymentMng manager;
	@Autowired
	private LogMng logMng;
}